﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Graphics.PackedVector;

namespace FrogEngine
{
	public class FireParticleSettings : ParticleSettings<SimpleGPUParticleVertex>
	{
		// Name of the texture used by this particle system.
		public override string TextureAssetName { get { return "fire"; } }

		// Maximum number of particles that can be displayed at one time.
		public override int MaxParticles { get { return 10000; } }

		// How long these particles will last.
		public override float LifeTime { get { return 2f; } }

		// If greater than zero, some particles will last a shorter time than others.
		public float DurationRandomness = 1;

		// Controls how much particles are influenced by the velocity of the object
		// which created them. You can see this in action with the explosion effect,
		// where the flames continue to move in the same direction as the source
		// projectile. The projectile trail particles, on the other hand, set this
		// value very low so they are less affected by the velocity of the projectile.
		public float EmitterVelocitySensitivity = 1;

		// Range of values controlling how much X and Z axis velocity to give each
		// particle. Values for individual particles are randomly chosen from somewhere
		// between these limits.
		public float MinHorizontalVelocity = 0;
		public float MaxHorizontalVelocity = 15;

		// Range of values controlling how much Y axis velocity to give each particle.
		// Values for individual particles are randomly chosen from somewhere between
		// these limits.
		public float MinVerticalVelocity = -10;
		public float MaxVerticalVelocity = 30;

		// Direction and strength of the gravity effect. Note that this can point in any
		// direction, not just down! The fire effect points it upward to make the flames
		// rise, and the smoke plume points it sideways to simulate wind.
		public Vector3 Gravity = new Vector3(0, 15, 0);


		// Controls how the particle velocity will change over their lifetime. If set
		// to 1, particles will keep going at the same speed as when they were created.
		// If set to 0, particles will come to a complete stop right before they die.
		// Values greater than 1 make the particles speed up over time.
		public float EndVelocity = 1;


		// Range of values controlling the particle color and alpha. Values for
		// individual particles are randomly chosen from somewhere between these limits.
		public Color MinColor = new Color(255, 255, 255, 10);
		public Color MaxColor = new Color(255, 255, 255, 40);


		// Range of values controlling how fast the particles rotate. Values for
		// individual particles are randomly chosen from somewhere between these
		// limits. If both these values are set to 0, the particle system will
		// automatically switch to an alternative shader technique that does not
		// support rotation, and thus requires significantly less GPU power. This
		// means if you don't need the rotation effect, you may get a performance
		// boost from leaving these values at 0.
		public float MinRotateSpeed = 0;
		public float MaxRotateSpeed = 0;


		// Range of values controlling how big the particles are when first created.
		// Values for individual particles are randomly chosen from somewhere between
		// these limits.
		public float MinStartSize = 100;
		public float MaxStartSize = 150;


		// Range of values controlling how big particles become at the end of their
		// life. Values for individual particles are randomly chosen from somewhere
		// between these limits.
		public float MinEndSize = 150;
		public float MaxEndSize = 400;

		// Alpha blending settings.
		public override BlendState BlendState { get { return BlendState.Additive; } }

		public override void FillVertices(ref SimpleGPUParticleVertex v0, ref SimpleGPUParticleVertex v1, ref SimpleGPUParticleVertex v2, ref SimpleGPUParticleVertex v3, ref Vector3 pos, ref Vector3 vel, float time)
		{
			vel *= this.EmitterVelocitySensitivity;

			// Add in some random amount of horizontal velocity.
			float horizontalVelocity = MathHelper.Lerp(this.MinHorizontalVelocity,
													   this.MaxHorizontalVelocity,
													   (float)random.NextDouble());

			double horizontalAngle = random.NextDouble() * MathHelper.TwoPi;

			vel.X += horizontalVelocity * (float)Math.Cos(horizontalAngle);
			vel.Z += horizontalVelocity * (float)Math.Sin(horizontalAngle);

			// Add in some random amount of vertical velocity.
			vel.Y += MathHelper.Lerp(this.MinVerticalVelocity,
									 this.MaxVerticalVelocity,
									 (float)random.NextDouble());

			// Choose four random control values. These will be used by the vertex
			// shader to give each particle a different size, rotation, and color.
			Color randomValues = new Color((byte)random.Next(255),
										   (byte)random.Next(255),
										   (byte)random.Next(255),
										   (byte)random.Next(255));

			v0.position = pos; v0.Velocity = vel; v0.Random = randomValues; v0.Time = time; v0.Corner = new Short2(-1, -1);
			v1.position = pos; v1.Velocity = vel; v1.Random = randomValues; v1.Time = time; v1.Corner = new Short2(1, -1);
			v2.position = pos; v2.Velocity = vel; v2.Random = randomValues; v2.Time = time; v2.Corner = new Short2(1, 1);
			v3.position = pos; v3.Velocity = vel; v3.Random = randomValues; v3.Time = time; v3.Corner = new Short2(-1, 1);
		}
	}
}
